<template>
  <van-pull-refresh v-model="refresh" @refresh="handleRefresh">
    <div ref="oVrList" class="vr-list scroll-wrap">
      <div ref="oList" class="list scroll-list" :style="defineStyle">
        <template v-for="( item, index ) of dataListSlice" :key="item">
          <slot :item="item" :index="index"></slot>
        </template>
      </div>
      <div class="more" v-if="more">加载中... </div>
      <div class="more" v-if="finished">到底了...</div>
    </div>
  </van-pull-refresh>
</template>

<script setup>
import { onMounted, ref, watch } from "vue";

const props = defineProps({
  column: { type: Number, default: 1 },  //  默认只展示一列
  refreshing: { type: Boolean, default: false },
  finished: { type: Boolean, default: false },
  more: { type: Boolean, default: false },
  dataList: { type: Array, default: () => ([]) },
  width: { type: String, default: '100%' },
  height: { type: String, default: '100px' },
  defineStyle: { type: Object, default: () => ({}) }
})

const oVrList = ref(null);
const oList = ref(null);

const startIndex = ref(0);

const dataListCache = ref(props.dataList);
//  创建数据切片
const dataListSlice = ref([]);

const refresh = ref(props.refreshing);
const itemHeight = parseInt(props.height);
const initNum = ref(0);

const emit = defineEmits(['load', 'refresh']);

//  加载更多
const handleLoadMore = () => {
  emit('load');
}

//  下拉刷新
const handleRefresh = () => {
  //  利用回调函数 控制状态
  emit('refresh', () => {
    //  关闭
    refresh.value = false;
  });
}

//  监听 padding 的变化
watch(startIndex, (val) => {
  if (!props.finished) {
    oList.value.style['padding-top'] = val * itemHeight + 'px';
    sliceData(val, val + initNum.value);
  }
})

watch(() => props.dataList, (val) => {
  sliceData(startIndex.value, startIndex.value + initNum.value);
})

function formatDataList(data = []) {
  //  对数据进行浅拷贝
  const _data = [...data];
  if (props.column <= 1) return _data; //  一列 直接返回

  //  容器
  let arr = [];
  const result = _data.reduce((prev, item, index) => {
    if (index % props.column === 0) {
      const len = prev.length;
      prev[len] = [item];
      arr = prev[len];
    } else {
      arr.push(item);
    }

    return prev;
  }, []);

  return result;
}

onMounted(() => {
  //  初始化数据
  handleLoadMore();

  //  根据当前的尺寸 确定需要生成的元素个数
  initNum.value = Math.ceil(parseFloat(getComputedStyle(oVrList.value, null)['height']) / itemHeight * 1.8);

  //  初始化  
  sliceData(0, initNum.value);

  //  监听滚动事件
  oVrList.value.addEventListener('scroll', scrollFn, false);
});

//  截取数据
function sliceData(start, end) {
  dataListCache.value = formatDataList(props.dataList);
  dataListSlice.value = dataListCache.value.slice(start, end);
}

//  滚动事件
function scrollFn(ev) {
  startIndex.value = Math.floor(this.scrollTop / itemHeight);

  const dataListLen = props.dataList.length;
  const dataListSliceLen = dataListSlice.value.length * props.column;

  //  判断何时加载数据
  //  未到底，未加载更多状态， 才会发送请求
  if (!props.finished && !props.more) {
    // 计算最后一个数据的位置 
    const len = dataListLen - (startIndex.value + dataListSliceLen);

    //  还剩3个元素的时候发送请求
    if (len < 2) {
      handleLoadMore();
    }
  }
}
</script>

<style lang="scss" scoped>
.vr-list {
  position: relative;
  height: 100vh;
  overflow-y: auto;

  .item {
    height: 100px;
    border: 1px solid red;
    text-align: center;
    box-sizing: border-box;
    line-height: 100px;
    font-size: 24px;
  }

  .more {
    width: 100%;
    height: 6rem;
    line-height: 6rem;
    font-size: 1.4rem;
    text-align: center;
  }
}
</style>
